package handling.channel;

import database.BeePool;
import tools.FileoutputUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

public class MapleGuildRanking {
    private static MapleGuildRanking instance;
    private List<GuildRankingInfo> ranks;
    private List<levelRankingInfo> ranks1;
    private List<mesoRankingInfo> ranks2;
    private Map<String, List<bossLogRankingInfo>> bossLogRanks;
    private Map<Integer, List<JobRankingInfo>> JobRanks;

    public static MapleGuildRanking getInstance() {
        return MapleGuildRanking.instance;
    }

    public MapleGuildRanking() {
        this.ranks = (List<GuildRankingInfo>) new LinkedList();
        this.ranks1 = (List<levelRankingInfo>) new LinkedList();
        this.ranks2 = (List<mesoRankingInfo>) new LinkedList();
        this.JobRanks = (Map<Integer, List<JobRankingInfo>>) new HashMap();
        this.bossLogRanks = (Map<String, List<bossLogRankingInfo>>) new LinkedHashMap();
    }

    private void reloadBossLogRank(String bossName, boolean clear) {
        if (bossName == null && clear) {
            this.bossLogRanks.clear();
            return;
        }
        try (Connection con = BeePool.getConnection()) {
            try (PreparedStatement ps = con.prepareStatement("SELECT DISTINCT bosslog.log, bosslog.sz1, characters.`name` FROM bosslog LEFT JOIN characters ON bosslog.id = characters.id WHERE bosslog.log = ? ORDER BY bosslog.sz1 DESC LIMIT 100")) {
                ps.setString(1, bossName);
                ResultSet rs = ps.executeQuery();
                List<bossLogRankingInfo> rank = (List<bossLogRankingInfo>) new LinkedList();
                while (rs.next()) {
                    bossLogRankingInfo info = new bossLogRankingInfo(rs.getString("log"), rs.getString("name"), rs.getInt("sz1"));
                    if (info.getName() != null) {
                        rank.add(info);
                    }
                }
                this.bossLogRanks.put(bossName, rank);
                rs.close();
                ps.close();
                
            }
        } catch (SQLException e) {
            System.err.println("人物排行错误" + e);
        }
    }

    public List<bossLogRankingInfo> getBossLogRank(String bossName, int world) {
        if (this.bossLogRanks.isEmpty() || this.bossLogRanks.get(bossName) == null) {
            this.reloadBossLogRank(bossName, false);
        }
        List<bossLogRankingInfo> ranks = (List<bossLogRankingInfo>) new LinkedList();
        for (bossLogRankingInfo rank : this.bossLogRanks.get(bossName)) {
            ranks.add(rank);
        }
        return ranks;
    }

    public List<JobRankingInfo> getJobRank(int type) {
        if (this.JobRanks.get(Integer.valueOf(type)) == null || (this.JobRanks.get(Integer.valueOf(type))).isEmpty()) {
            this.loadJobRank(type);
        }
        return this.JobRanks.get(Integer.valueOf(type));
    }

    public List<GuildRankingInfo> getGuildRank() {
        if (this.ranks.isEmpty()) {
            this.reload();
        }
        return this.ranks;
    }

    public List<levelRankingInfo> getLevelRank() {
        if (this.ranks1.isEmpty()) {
            this.showLevelRank();
        }
        return this.ranks1;
    }

    public List<mesoRankingInfo> getMesoRank() {
        if (this.ranks2.isEmpty()) {
            this.showMesoRank();
        }
        return this.ranks2;
    }

    private void reload() {
        this.ranks.clear();
        ResultSet rs = null;
        PreparedStatement ps = null;
        try (Connection con = BeePool.getConnection()) {
            ps = con.prepareStatement("SELECT * FROM guilds ORDER BY `GP` DESC LIMIT 50");
            rs = ps.executeQuery();
            while (rs.next()) {
                GuildRankingInfo rank = new GuildRankingInfo(rs.getString("name"), rs.getInt("GP"), rs.getInt("logo"), rs.getInt("logoColor"), rs.getInt("logoBG"), rs.getInt("logoBGColor"));
                this.ranks.add(rank);
            }
            rs.close();
            ps.close();
            
        } catch (SQLException e) {
            System.err.println("Error handling guildRanking");
            FileoutputUtil.outError("logs/资料库异常.txt", (Throwable) e);
        }

    }

    private void showLevelRank() {
        this.ranks1.clear();
        PreparedStatement ps = null;
        ResultSet rs = null;
        try (Connection con = BeePool.getConnection()) {
            ps = con.prepareStatement("SELECT * FROM characters WHERE gm < 1 ORDER BY `level` DESC LIMIT 100");
            rs = ps.executeQuery();
            while (rs.next()) {
                levelRankingInfo rank1 = new levelRankingInfo(rs.getString("name"), rs.getInt("level"), rs.getInt("str"), rs.getInt("dex"), rs.getInt("int"), rs.getInt("luk"));
                this.ranks1.add(rank1);
            }
            rs.close();
            ps.close();
            
        } catch (SQLException e) {
            System.err.println("未能显示等级排行");
            FileoutputUtil.outError("logs/资料库异常.txt", (Throwable) e);
        }
    }

    private void showMesoRank() {
        this.ranks2.clear();
        ResultSet rs = null;
        PreparedStatement ps = null;
        try (Connection con = BeePool.getConnection()) {
            ps = con.prepareStatement("SELECT *, ( chr.meso + s.meso ) as money FROM `characters` as chr , `storages` as s WHERE chr.gm < 1  AND s.accountid = chr.accountid ORDER BY money DESC LIMIT 20");
            rs = ps.executeQuery();
            while (rs.next()) {
                mesoRankingInfo rank2 = new mesoRankingInfo(rs.getString("name"), rs.getLong("money"), rs.getInt("str"), rs.getInt("dex"), rs.getInt("int"), rs.getInt("luk"));
                this.ranks2.add(rank2);
            }
            rs.close();
            ps.close();
            
        } catch (SQLException e) {
            System.err.println("未能显示财产排行");
            FileoutputUtil.outError("logs/资料库异常.txt", (Throwable) e);
        }
    }

    private void loadJobRank(int type) {
        if (this.JobRanks.get(Integer.valueOf(type)) != null) {
            (this.JobRanks.get(Integer.valueOf(type))).clear();
        }
        String jobRange = "";
        if (type == 1) {
            jobRange = "and job >= '100' and job <= '132'";
        } else if (type == 2) {
            jobRange = "and job >= '200' and job <= '232'";
        } else if (type == 3) {
            jobRange = "and job >= '300' and job <= '322'";
        } else if (type == 4) {
            jobRange = "and job >= '400' and job <= '422'";
        } else if (type == 5) {
            jobRange = "and job >= '500' and job <= '522'";
        } else if (type == 6) {
            jobRange = "and job >= '2000' and job <= '2112'";
        }
        ResultSet rs = null;
        PreparedStatement ps = null;
        try (Connection con = BeePool.getConnection()) {
            ps = con.prepareStatement("SELECT * FROM characters WHERE gm = 0 " + jobRange + " and accountid in (select id from accounts where banned= '0') ORDER BY `level` DESC LIMIT 10");
            rs = ps.executeQuery();
            LinkedList<JobRankingInfo> JobRankList = (LinkedList<JobRankingInfo>) new LinkedList();
            while (rs.next()) {
                JobRankingInfo JobRank = new JobRankingInfo(rs.getString("name"), rs.getInt("level"), rs.getInt("job"), rs.getInt("str"), rs.getInt("dex"), rs.getInt("int"), rs.getInt("luk"));
                JobRankList.add(JobRank);
            }
            this.JobRanks.put(Integer.valueOf(type), JobRankList);
            rs.close();
            ps.close();
            
        } catch (SQLException e) {
            FileoutputUtil.outError("logs/资料库异常.txt", (Throwable) e);
            System.err.println("未能显示职业" + type + "排行");
        }
    }

    static {
        instance = new MapleGuildRanking();
    }

    public static class mesoRankingInfo {
        private String name;
        private long meso;
        private int str;
        private int dex;
        private int _int;
        private int luk;

        public mesoRankingInfo(String name, long meso, int str, int dex, int intt, int luk) {
            this.name = name;
            this.meso = meso;
            this.str = str;
            this.dex = dex;
            this._int = intt;
            this.luk = luk;
        }

        public String getName() {
            return this.name;
        }

        public long getMeso() {
            return this.meso;
        }

        public int getStr() {
            return this.str;
        }

        public int getDex() {
            return this.dex;
        }

        public int getInt() {
            return this._int;
        }

        public int getLuk() {
            return this.luk;
        }
    }

    public static class JobRankingInfo {
        private String name;
        private int level;
        private int str;
        private int dex;
        private int _int;
        private int luk;
        private int job;

        public JobRankingInfo(String name, int level, int job, int str, int dex, int intt, int luk) {
            this.name = name;
            this.level = level;
            this.job = job;
            this.str = str;
            this.dex = dex;
            this._int = intt;
            this.luk = luk;
        }

        public String getName() {
            return this.name;
        }

        public int getLevel() {
            return this.level;
        }

        public int getStr() {
            return this.str;
        }

        public int getDex() {
            return this.dex;
        }

        public int getInt() {
            return this._int;
        }

        public int getLuk() {
            return this.luk;
        }

        public int getJob() {
            return this.job;
        }
    }

    public static class levelRankingInfo {
        private String name;
        private int level;
        private int str;
        private int dex;
        private int _int;
        private int luk;

        public levelRankingInfo(String name, int level, int str, int dex, int intt, int luk) {
            this.name = name;
            this.level = level;
            this.str = str;
            this.dex = dex;
            this._int = intt;
            this.luk = luk;
        }

        public String getName() {
            return this.name;
        }

        public int getLevel() {
            return this.level;
        }

        public int getStr() {
            return this.str;
        }

        public int getDex() {
            return this.dex;
        }

        public int getInt() {
            return this._int;
        }

        public int getLuk() {
            return this.luk;
        }
    }

    public static class GuildRankingInfo {
        private String name;
        private int gp;
        private int logo;
        private int logocolor;
        private int logobg;
        private int logobgcolor;

        public GuildRankingInfo(String name, int gp, int logo, int logocolor, int logobg, int logobgcolor) {
            this.name = name;
            this.gp = gp;
            this.logo = logo;
            this.logocolor = logocolor;
            this.logobg = logobg;
            this.logobgcolor = logobgcolor;
        }

        public String getName() {
            return this.name;
        }

        public int getGP() {
            return this.gp;
        }

        public int getLogo() {
            return this.logo;
        }

        public int getLogoColor() {
            return this.logocolor;
        }

        public int getLogoBg() {
            return this.logobg;
        }

        public int getLogoBgColor() {
            return this.logobgcolor;
        }
    }

    public static class bossLogRankingInfo {
        private String name;
        private String bossName;
        private int count;

        public bossLogRankingInfo(String bossName, String name, int count) {
            this.bossName = bossName;
            this.name = name;
            this.count = count;
        }

        public String getBossName() {
            return this.bossName;
        }

        public String getName() {
            return this.name;
        }

        public int getCount() {
            return this.count;
        }
    }
}
